package com.sjb.sixteen_journey_backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sjb.sixteen_journey_backend.common.ImagesProperties;
import com.sjb.sixteen_journey_backend.common.R;
import com.sjb.sixteen_journey_backend.entity.*;
import com.sjb.sixteen_journey_backend.entity.dto.MyMapDto;
import com.sjb.sixteen_journey_backend.entity.vo.MyMapVo;
import com.sjb.sixteen_journey_backend.entity.vo.UserBaseMsgVo;
import com.sjb.sixteen_journey_backend.mapper.CommonnessMapper;
import com.sjb.sixteen_journey_backend.mapper.FollowerMapper;
import com.sjb.sixteen_journey_backend.mapper.MyMapMapper;
import com.sjb.sixteen_journey_backend.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sjb.sixteen_journey_backend.utils.AliOssUtil;
import com.sjb.sixteen_journey_backend.utils.ThreadLocalUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 我的地图表 服务实现类
 * </p>
 *
 * @author jcz
 * @since 2024-07-25
 */
@Service
public class MyMapServiceImpl extends ServiceImpl<MyMapMapper, MyMap> implements IMyMapService {


    @Autowired
    private IUserService userService;

    @Autowired
    private IMapSiteService mapSiteService;

    @Autowired
    private IMapRouteService mapRouteService;

    @Autowired
    private CommonnessMapper commonnessMapper;

    @Autowired
    private ICommentService commentService;
    @Autowired
    private ImagesProperties imagesProperties;

    @Autowired
    private FollowerMapper followerMapper;
    @Override
    public R<MyMap> addMyMap(MyMapDto myMapDto) {
        try {
            MyMap myMap = new MyMap();
            BeanUtils.copyProperties(myMapDto, myMap);
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer userId = (Integer) map.get("id");
            String username = (String) map.get("username");
            myMap.setUserId(userId);
            myMap.setMapName(username + "的" + myMap.getSiteName() + "地图");
            if (this.save(myMap)) {
                myMap = this.getById(myMap.getMyMapId());
                User user = userService.getById(myMap.getUserId());
                UserBaseMsgVo userBaseMsgVo = new UserBaseMsgVo();
                BeanUtils.copyProperties(user, userBaseMsgVo);
                myMap.setUser(userBaseMsgVo);
                myMap.setIs_followedByUser(false);
                return R.success(myMap, "添加地图成功");
            }
            return R.error("添加地图失败");
        } catch (BeansException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R removeMyMap(Integer myMapId) {
        try {
            MyMap myMap = this.getById(myMapId);
            if (myMap == null) {
                return R.error("删除失败，该地图不存在");
            }
            if (this.removeById(myMapId)) {
//                String rootPath = System.getProperty("user.dir") + imagesProperties.getRootPath()+imagesProperties.getMap();
//                //先获取图片名
//                String img = myMap.getPath().substring(myMap.getPath().lastIndexOf('/') + 1);
//                //先删除原来的图片
//                File f = new File(rootPath + img);
//                f.delete();
                return R.success(null, "删除成功");
            }
            return R.error("删除地图失败");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<MyMap> showMapById(Integer id,Boolean f) {
        try {

            MyMap myMap = this.getById(id);
            if(f){
                UpdateWrapper<MyMap> update = Wrappers.update();
                update.eq("my_map_id", id);
                update.set("pv",myMap.getPv()+1);
                this.update(update);
                myMap = this.getById(id);
            }



            if (myMap == null) return R.error("地图不存在");
            //获取地图创建者的用户id,用户名，头像
            User user = userService.getById(myMap.getUserId());
            UserBaseMsgVo userBaseMsgVo = new UserBaseMsgVo();
            BeanUtils.copyProperties(user, userBaseMsgVo);
            myMap.setUser(userBaseMsgVo);

            //获取地图的标记点
            QueryWrapper<MapSite> wrapper = Wrappers.query();
            wrapper.eq("my_map_id", id);
            List<MapSite> mapSites = mapSiteService.list(wrapper);
            myMap.setMapSite(mapSites);

            //获取地图的路线
            QueryWrapper<MapRoute> wrapperRoute = Wrappers.query();
            wrapper.eq("my_map_id", id);
            List<MapRoute> mapRoutes = mapRouteService.list(wrapperRoute);

            //获取地图路线的标记点
            for(MapRoute route : mapRoutes){
                //获取路线的站点id
                List<Integer> collect = Arrays.stream(route.getSiteIdList().split(","))
                    .map(Integer::valueOf)
                        .collect(Collectors.toList());
                double[][] sites = new double[collect.size()][2];
                int index = 0;
                for(Integer i : collect){
                    MapSite mapSite = mapSiteService.getById(i);
                    BigDecimal siteLng = mapSite.getSiteLng();
                    BigDecimal siteLat = mapSite.getSiteLat();
                    //为sites插入数据siteLng siteLat
                    sites[index][0] = siteLng.doubleValue();
                    sites[index][1] = siteLat.doubleValue();
                    index++;
                }
                route.setRoute(sites);
            }
            myMap.setMapRoute(mapRoutes);
            //设置评论数量和当前用户对该用户是否关注
            myMap = this.setCountAndFollow(myMap);

            return R.success(myMap,"获取地图成功");
        } catch (BeansException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R changeAuthorityIsPublic(Integer id, Boolean isPublic) {
        try {
            if(this.getById(id)==null) return R.error("修改失败，该地图不存在");
            UpdateWrapper<MyMap> update = Wrappers.update();
            update.eq("my_map_id", id);
            update.set("authority",isPublic);
            this.update(new MyMap(),update);
            R<MyMap> myMapR = this.showMapById(id,false);
            return R.success(myMapR.getData(),"修改可见成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<MyMap> changeMapName(Integer id, String name) {
        try {
            if(this.getById(id)==null) return R.error("修改失败，该地图不存在");
            UpdateWrapper<MyMap> update = Wrappers.update();
            update.eq("my_map_id", id);
            update.set("map_name",name);
            this.update(new MyMap(),update);
            R<MyMap> myMapR = this.showMapById(id,false);
            return R.success(myMapR.getData(),"修改地图名成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<MyMap> changeMapAvatar(Integer id, MultipartFile file) {
        try {
            if(this.getById(id)==null) return R.error("修改失败，该地图不存在");
            MyMap myMap = this.getById(id);
            String path = file.getOriginalFilename();

//            String rootPath = System.getProperty("user.dir") + imagesProperties.getRootPath()+imagesProperties.getMap();
            //先删除本地原来的图片
//            if(myMap!=null){
//                String img = myMap.getPath().substring(myMap.getPath().lastIndexOf('/') + 1);
//                File f = new File(rootPath + img);
//                f.delete();
//            }
            //获得新传入的图片名，修改图片名为唯一的
            String fileName = UUID.randomUUID().toString() + path.substring(path.lastIndexOf("."));
            String url = AliOssUtil.uploadFile(fileName,file.getInputStream());


//            file.transferTo(new File(rootPath + fileName));

            UpdateWrapper<MyMap> update = Wrappers.update();
            update.eq("my_map_id", id);
//            update.set("path",imagesProperties.getVisitImagePath()+imagesProperties.getMap() +fileName);
            update.set("path",url);

            this.update(new MyMap(),update);
            R<MyMap> myMapR = this.showMapById(id,false);
            return R.success(myMapR.getData(),"修改地图封面成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<MyMap> changeMapRemarks(Integer id, String content) {
        try {
            if(this.getById(id)==null) return R.error("修改失败，该地图不存在");
            UpdateWrapper<MyMap> update = Wrappers.update();
            update.eq("my_map_id", id);
            update.set("remarks",content);
            this.update(new MyMap(),update);
            R<MyMap> myMapR = this.showMapById(id,false);
            return R.success(myMapR.getData(),"修改地图备注成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<List<MyMapVo>> showAllMap() {
        try {
            //获取所有公开的地图
            QueryWrapper<MyMap> myMapWrapper = Wrappers.query();
            myMapWrapper.eq("authority", false);
            List<MyMap> myMaps = this.list(myMapWrapper);
            if(myMaps.size()<=0) return R.success(null,"没有任何地图");

            List<MyMapVo> myMapVos = this.getListMyMapVo(myMaps);

            return R.success(myMapVos,"获取所有地图成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<List<MyMapVo>> showCityMap(String city) {
        try {
            //获取所有公开的地图
            QueryWrapper<MyMap> myMapWrapper = Wrappers.query();
            myMapWrapper.eq("authority", false);
            myMapWrapper.eq("site_name", city);
            List<MyMap> myMaps = this.list(myMapWrapper);
            if(myMaps.size()<=0) return R.success(null,"没有任何地图");

            List<MyMapVo> myMapVos = this.getListMyMapVo(myMaps);

            return R.success(myMapVos,"获取所有地图成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<List<MyMapVo>> showMapByUserId() {
        try {
            Map<String, Object> map = ThreadLocalUtil.get();
            Integer userId = (Integer) map.get("id");
            QueryWrapper<MyMap> myMapWrapper = Wrappers.query();
            myMapWrapper.eq("user_id", userId);
            List<MyMap> myMaps = this.list(myMapWrapper);
            if(myMaps.size()<=0) return R.success(null,"该用户没有建立地图");

            List<MyMapVo> myMapVos = this.getListMyMapVo(myMaps);


            return R.success(myMapVos,"成功获取当前所有地图");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<MyMapVo> getListMyMapVo(List<MyMap> myMaps) {
        List<MyMapVo> myMapVos = new ArrayList<>();
        for(MyMap my:myMaps){
            MyMapVo myMapVo = new MyMapVo();
            myMapVo.setId(my.getMyMapId());
            myMapVo.setMapName(my.getMapName());
            myMapVo.setPath(my.getPath());
            myMapVo.setPv(my.getPv());

            //获取该地图所标记的地点数量
            QueryWrapper<MapSite> query = Wrappers.query();
            query.eq("my_map_id",my.getMyMapId());
            long count = mapSiteService.count(query);
            myMapVo.setSite(count);

            //获取该地图所标记的地点数量
            QueryWrapper<MapRoute> wrapper = Wrappers.query();
            query.eq("my_map_id",my.getMyMapId());
            count = mapRouteService.count(wrapper);
            myMapVo.setRoute(count);
            myMapVos.add(myMapVo);
        }
        return myMapVos;
    }

    @Override
    public R<List<MyMapVo>> showPublicMapById(Integer id) {
        try {
//            Map<String, Object> map = ThreadLocalUtil.get();
//            Integer userId = (Integer) map.get("id");
            QueryWrapper<MyMap> myMapWrapper = Wrappers.query();
            myMapWrapper.eq("user_id", id);
            myMapWrapper.eq("authority", false);
            List<MyMap> myMaps = this.list(myMapWrapper);
            if(myMaps.size()<=0) return R.success(null,"该用户没有建立地图");
            List<MyMapVo> myMapVos = this.getListMyMapVo(myMaps);


            return R.success(myMapVos,"成功获取该用户所有公开的地图");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<List<MyMapVo>> showPublicMapByKeyWords(String keyWords) {
        try {
            QueryWrapper<MyMap> myMapWrapper = Wrappers.query();
            myMapWrapper.like("map_name", keyWords);
            myMapWrapper.eq("authority", false);
            List<MyMap> myMaps = this.list(myMapWrapper);
            if(myMaps.size()<=0) return R.success(null,"暂时没有该地图");

            List<MyMapVo> myMapVos = this.getListMyMapVo(myMaps);


            return R.success(myMapVos,"成功获取该用户所有公开的地图");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private MyMap setCountAndFollow(MyMap myTime) {
        Map<String, Object> map = ThreadLocalUtil.get();

        //我的此刻的评论数量
        QueryWrapper<Comment> query = Wrappers.query();
        query.eq("module_status",myTime.getStatus());
        query.eq("module_id", myTime.getMyMapId());
        long count = commentService.count(query);
        myTime.setCommentCount(count);

        Follower follower = new Follower();
        if(map!=null){
            Integer userId = (Integer) map.get("id");
            //当前用户对该用户是否关注
            QueryWrapper<Follower> followerQueryWrapper = Wrappers.query();
            followerQueryWrapper.eq("user_id",userId);
            followerQueryWrapper.eq("fans_id", myTime.getUserId());
            follower = followerMapper.selectOne(followerQueryWrapper);
        }
        myTime.setIs_followedByUser(follower==null ? false :follower.getStatus());
        return myTime;
    }
}
